#ifndef _USB_MEDIA_H
#define _USB_MEDIA_H

#include <types.h>
#include <list.h>

/**
 * @name usb media public interface
 */
/*@{*/
/**
 * @brief Start usb media monitor
 *
 * When the monitor starts to run, it first query all usb media and add them
 * to an internal list. Then, it monitors the change event of usb media, like
 * add or remove, in the background and modifies the internal list.<br />
 * Use usb_media_register_event_handler() and usb_media_unregister_event_handler()
 * to register and unregister usb media event handler.
  */
extern void usb_media_start_monitor();
/**
 * @brief Stop usb media monitor
 */
extern void usb_media_stop_monitor();

/**
 * @enum um_event_type
 * Types of usb media events
 */
/** @var um_event_type UM_ADD
 * Event for usb medium added and mounted
 */
/** @var um_event_type UM_REMOVE
 * Event for usb medium unmounted
 */

#define UM_EVENT_LIST \
EXPAND_UM_EVENT(UM_ADD) \
EXPAND_UM_EVENT(UM_REMOVE)

#define EXPAND_UM_EVENT(e) e,
enum um_event_type {
    UM_EVENT_LIST
    UM_EVENT_NUM /**< Not real event, but number of events */
};
#undef EXPAND_UM_EVENT

#define UM_ROOT_PATH_MAX 256

struct usb_media {
    char um_root[UM_ROOT_PATH_MAX]; /**< usb medium root path (= mount point) */
    bool syncup_enabled; /**< If turned on, this device is set up for syncup */

    /* <private> */
    struct list_head um_list;
};

typedef void (*um_event_handler_t) (const struct usb_media *);

extern void usb_media_register_event_handler(enum um_event_type evt_type, um_event_handler_t func);
extern void usb_media_unregister_event_handler(enum um_event_type evt_type, um_event_handler_t func);

/*@} End of usb media public interface */

/* internal usage */
extern void usb_media_check_syncup(struct usb_media *um);

/* Debug only */
extern void usb_media_print_list();

#endif /* ! _USB_MEDIA_H */
